package mmodel

import (
	"fmt"
	"reflect"
)

var SToString = func(data any) string {
	return fmt.Sprintf("%v", data)
}

type Comparator interface {
	Equal(data *any) bool
}

type Pair struct {
	Key any `json:"key"`
	Val any `json:"val"`
}

func (domain *Pair) Equal(data *any) bool {
	if reflect.TypeOf(*data).Name() == "Pair" {
		p := (*data).(Pair)
		return reflect.DeepEqual(domain.Key, p.Key)
	}
	return false
}

type ListMap struct {
	dataMap map[any]*Pair
	keys    []any
	index   int
}

func NewListMap(cap int) *ListMap {
	return &ListMap{
		map[any]*Pair{},
		make([]any, 0, cap),
		0,
	}
}
func (domain *ListMap) Put(key any, val any) {
	if pair := domain.dataMap[key]; pair != nil {
		pair.Val = val
		index := pair.Key.(int)
		domain.keys[index] = key
	} else {
		domain.keys = append(domain.keys, key)
		domain.dataMap[key] = &Pair{len(domain.keys) - 1, val}
	}
}
func (domain *ListMap) PutNotFound(key any, val any) bool {
	if pair := domain.dataMap[key]; pair == nil {
		domain.keys = append(domain.keys, key)
		domain.dataMap[key] = &Pair{len(domain.keys) - 1, val}
		return true
	}
	return false
}
func (domain *ListMap) PutExists(key any, val any) bool {
	if pair := domain.dataMap[key]; pair != nil {
		pair.Val = val
		index := pair.Key.(int)
		domain.keys[index] = key
		return true
	}
	return false
}
func (domain *ListMap) Length() int {
	return len(domain.keys)
}

func (domain *ListMap) Get(index int) any {
	if pair := domain.dataMap[domain.keys[index]]; pair != nil {
		return pair.Val
	}
	return nil
}
func (domain *ListMap) GetV(key any) any {
	if pair := domain.dataMap[key]; pair != nil {
		return pair.Val
	}
	return nil
}
func (domain *ListMap) Set(index int, val any) {
	pair := domain.dataMap[domain.keys[index]]
	pair.Val = val
}
func (domain *ListMap) HasNext() bool {
	return domain.index < len(domain.keys)
}
func (domain *ListMap) Next() any {
	pair := domain.dataMap[domain.keys[domain.index]]
	domain.index = domain.index + 1
	return pair.Val
}
func (domain *ListMap) Index() int {
	return domain.index
}
func (domain *ListMap) RestIndex() {
	domain.index = 0
}

func (domain *ListMap) JsonMap(toString func(object any) string) (data map[string]any) {
	data = map[string]any{}
	for index := range domain.keys {
		oldKey := domain.keys[index]
		key := toString(oldKey)
		data[key] = (*domain.dataMap[oldKey]).Val
	}
	return data
}
func (domain *ListMap) Map() (data map[any]any) {
	data = map[any]any{}
	for index := range domain.keys {
		key := domain.keys[index]
		data[key] = (*domain.dataMap[key]).Val
	}
	return data
}
